home *** CD-ROM | disk | FTP | other *** search
- From: roemer@informatik.uni-frankfurt.de
- Posted-Date: Mon, 17 Jan 94 15:52:26 "MET
- Received-Date: Mon, 17 Jan 94 15:52:26 +0100
- Message-Id: <9401171452.AA01122@diomedes.rbi.informatik.uni-frankfurt.de>
- Subject: MINTOS: Porting Library !?
- To: mint@atari.archive.umich.edu
- Date: Mon, 17 Jan 94 15:52:26 "MET
- Mailer: Elm [revision: 70.85]
-
- Micheal Hohmuth writes:
-
- > Rather, we should concentrate on things that have to be generalized
- > in order to reach a state where Unix software con be compiled out of
- > the box.
-
- Yes, I would love that state, too. But obviously there are some problems,
- which cannot be solved transparently in the library without changing the
- MiNT kernel. Probably everyone who ever ported unix software to MiNT came
- across those things.
-
- I think we should try to find general solutions for those problems which
- require only minimal changes to the source code (ie no mayor rewrites).
- Any other opinions, I think not :-).
-
- So I'm going to start a list of what I call 'elegant solutions' to some
- of the above problems. Probably there are lots of such 'workarounds' out
- there. It would be great to have a look at and collect them.
- Perhaps we could even build a nonstandart library containing useful code
- for porting unix software.
-
- Here are my suggestions:
-
- (1) Mint's fork() blocks the parent until the child exec()'s or
- exit()'s. This is a problem in constructs like:
-
- if (!fork()) exit();
-
- Here is a workaround, which uses tfork() and requires only
- minimal changes to the source. Using tfork() directly often
- requires restructuring of the source.
-
- ------------------------ cut ----------------------------
- #include <unistd.h>
- #include <fcntl.h>
- #include <ioctl.h>
- #include <setjmp.h>
- #include <signal.h>
-
- static int fd_flags[32];
- static jmp_buf jmpbuf;
- static long sigmask;
- static struct sigaction sigacts[32];
-
- int
- child_proc (long pip)
- {
- char buf;
- int i;
-
- sigsetmask (~0L);
- if (read (pip, &buf, 1)) exit (0);
- close (pip);
- for (i = 0; i < 32; ++i) {
- if (fd_flags[i] >= 0)
- fcntl (i, F_SETFD, fd_flags[i]);
- }
- for (i = 0; i < 32; ++i) {
- sigaction (i, &sigacts[i], 0);
- }
- longjmp (jmpbuf, 1);
- }
-
- int
- __fork_and_exit (void)
- {
- int i, pip[2];
-
- sigmask = sigsetmask (~0L);
- if (pipe (pip) < 0) return -1;
- for (i = 0; i < 32; ++i) {
- fd_flags[i] = fcntl (i, F_GETFD, 0);
- fcntl (i, F_SETFD, i == pip[1] ? FD_CLOEXEC : 0);
- }
- for (i = 0; i < 32; ++i) {
- sigaction (i, 0, &sigacts[i]);
- }
- if (!setjmp (jmpbuf)) {
- /* parent */
- tfork (child_proc, pip[0]);
- exit (0);
- }
- /* child */
- sigsetmask (sigmask);
- return 0;
- }
- --------------------------- cut ----------------------------
-
- __fork_and_exit() preserves file handles, signal handlers
- and the set of masked signals to the child, much like fork()
- does.
- Its functionlity is the same as for if (!fork()) exit().
-
- (2) Another problem is that Mint/MintLibs read()/write() have
- no POSIX nonblocking mode (activated with the O_NONBLOCK
- fcntl()) flags. The difference to O_NDELAY nonblocking mode
- is that read()/write() return -1 and EWOULDBLOCK/EAGAIN in
- errno if no data/space is available at all (instead of
- returning 0 when O_NDELAY is actice).
- I know Entropy worked on this, but in the MintLibs this stuff
- is commented out.
- My solution is probably not more than a hack. Improvements
- are appreciated.
-
- -------------------------- cut -------------------------------
- #include <fcntl.h>
- #include <errno.h>
- #include <ioctl.h>
- #include <osbind.h>
- #include <mintbind.h>
-
- #define UNLIMITED 1000000000L
-
- int
- __posixish_read (int fd, void *buffer, unsigned int buflen)
- {
- int r, s;
- unsigned long buf;
- extern int errno;
-
- r = Fread (fd, buflen, buffer);
- if (r <= 0) {
- if (r < 0) {
- errno = -r;
- return -1;
- }
- if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
- s = Fcntl (fd, &buf, FIONREAD);
- if (!s && buf < UNLIMITED) {
- errno = EWOULDBLOCK;
- return -1;
- }
- }
- }
- return r;
- }
-
- int
- __posixish_write (int fd, void *buffer, unsigned int buflen)
- {
- int r, s;
- unsigned long buf;
- extern int errno;
-
- r = Fwrite (fd, buflen, buffer);
- if (r <= 0) {
- if (r < 0) {
- errno = -r;
- return -1;
- }
- if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
- s = Fcntl (fd, &buf, FIONWRITE);
- if (!s && buf < UNLIMITED) {
- errno = EWOULDBLOCK;
- return -1;
- }
- }
- }
- return r;
- }
-
- ------------------------- cut -----------------------------------
-
- When only O_NONBLOCK nonblocking mode is used, you could
- then
- #define read(a,b,c) __posixish_read(a,b,c)
- #define write(a,b,c) __posixish_write(a,b,c)
- #define O_NONBLOCK O_NDELAY
- and use this as a reasonabe emulation.
-
- (3) select()ing for exceptional conditions does not work.
- This is a pitty for sockets (TCP) and out of band data.
- Perhaps we could do a workaround using SIGURG.
- Any suggestions?
-
- Waiting for your opinion and suggestions,
- Kay.
-